package org.gwtde.client.views;

import java.util.HashMap;
import java.util.Map;

import net.mygwt.ui.client.Events;
import net.mygwt.ui.client.MyDOM;
import net.mygwt.ui.client.Registry;
import net.mygwt.ui.client.event.BaseEvent;
import net.mygwt.ui.client.event.Listener;
import net.mygwt.ui.client.event.ShellListener;
import net.mygwt.ui.client.mvc.AppEvent;
import net.mygwt.ui.client.mvc.Controller;
import net.mygwt.ui.client.mvc.Dispatcher;
import net.mygwt.ui.client.mvc.View;
import net.mygwt.ui.client.util.Format;
import net.mygwt.ui.client.util.Rectangle;
import net.mygwt.ui.client.widget.DesktopShell;
import net.mygwt.ui.client.widget.Shell;
import net.mygwt.ui.client.widget.ShellManager;
import net.mygwt.ui.client.widget.ToolButton;
import net.mygwt.ui.client.widget.WidgetContainer;

import org.gwtde.client.Desktop;
import org.gwtde.client.DesktopEvents;
import org.gwtde.client.model.AppLink;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Frame;

public class ShellView extends View {

	private static Map sShellNames = new HashMap();

	private String mURL;
	private Shell mShell;
	private Frame mFrame;

	private boolean mMaximized = false;
	private boolean mRolledUp = false;
	private Rectangle mOldBounds = null;

	ShellListener mListener = new ShellListener() {
		public void shellDeactivated(BaseEvent be) {
			Shell shell = (Shell) be.widget;
			Dispatcher.forwardEvent(new AppEvent(DesktopEvents.ShellDeActivated, shell));
		}

		public void shellClosed(BaseEvent be) {
			Shell shell = (Shell) be.widget;
			sShellNames.remove(shell.getText());
			Dispatcher.forwardEvent(new AppEvent(DesktopEvents.ShellClosed, shell));
		}

		public void shellActivated(BaseEvent be) {
			Shell shell = (Shell) be.widget;
			Dispatcher.forwardEvent(new AppEvent(DesktopEvents.ShellActivated, shell));
		}
	};

	public ShellView(Controller pController) {
		super(pController);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.mygwt.ui.client.mvc.View#initialize()
	 */
	protected void initialize() {
		final Rectangle desktopBounds = Desktop.getBounds();

		mShell = new DesktopShell();

		mShell.setSize((int) (Desktop.getClientWidth() / 1.5), (int) (Desktop.getClientHeight() / 1.333));

		mShell.setIconStyle("icon-shell");
		mShell.setText("GWT Desktop Shell");

		DOM.setStyleAttribute(mShell.getContent().getElement(), "backgroundColor", "FFFFFF;");

		final DockView dock = (DockView) Registry.get("dock");

		ToolButton refresh = new ToolButton("my-tool-refresh");
		refresh.setTitle("Reload current shell");
		refresh.addListener(Events.Click, new Listener() {
			public void handleEvent(BaseEvent be) {
				mFrame.setUrl(mURL);
			}
		});
		mShell.addTool(refresh);

		final ToolButton roll = new ToolButton("my-tool-minus");
		roll.setTitle("Roll up current shell");
		roll.addListener(Events.Click, new Listener() {
			public void handleEvent(BaseEvent be) {
				if (mRolledUp) {
					if (mMaximized) {
						mShell.setHeight(Desktop.getClientHeight());
					} else if (mOldBounds != null) {
						mShell.setHeight(mOldBounds.height);
						mOldBounds = null;
					} else {
						mShell.setHeight((int) (Desktop.getClientHeight() / 1.333));
					}
					mRolledUp = false;
					roll.changeStyle("my-tool-minus");
				} else {
					if (!mMaximized) {
						mOldBounds = mShell.getBounds();
					}
					mShell.setHeight(50);
					mRolledUp = true;
					roll.changeStyle("my-tool-plus");
				}
			}
		});
		// mShell.addTool(roll);

		final ToolButton minimize = new ToolButton("my-tool-minimize");
		minimize.setTitle("Minimize current shell");
		minimize.addListener(Events.Click, new Listener() {
			public void handleEvent(BaseEvent be) {
				mShell.hide();
			}
		});
		mShell.addTool(minimize);

		final ToolButton resize = new ToolButton("my-tool-maximize");
		resize.setTitle("Maximize/Restore current shell");
		resize.addListener(Events.Click, new Listener() {
			public void handleEvent(BaseEvent be) {

				if (mMaximized) {
					if (mOldBounds != null) {
						mShell.setBounds(mOldBounds);
						mOldBounds = null;
					} else {
						mShell.setSize((int) (Desktop.getClientWidth() / 1.5),
								(int) (Desktop.getClientHeight() / 1.333));
						mShell.center();
					}
					mMaximized = false;
					resize.changeStyle("my-tool-maximize");
					mRolledUp = false;
					roll.changeStyle("my-tool-minus");
				} else {
					if (!mRolledUp) {
						mOldBounds = mShell.getBounds();
					}
					Rectangle r = dock.getBounds();
					if (dock.isPinned() && (r.x - desktopBounds.x) == 0) {
						mShell.setBounds(new Rectangle(desktopBounds.x + r.width, desktopBounds.y, Desktop
								.getClientWidth()
								- r.width, Desktop.getClientHeight()));
					} else if (dock.isPinned()) {
						mShell.setBounds(new Rectangle(desktopBounds.x, desktopBounds.y, Desktop.getClientWidth()
								- r.width, Desktop.getClientHeight()));
					} else {
						mShell.setBounds(new Rectangle(desktopBounds.x, desktopBounds.y, Desktop.getClientWidth(),
								Desktop.getClientHeight()));
					}
					mMaximized = true;
					resize.changeStyle("my-tool-restore");
					mRolledUp = false;
					roll.changeStyle("my-tool-minus");
				}
				mShell.setResizeEnabled(!mMaximized);
				mShell.setDragEnabled(!mMaximized);
			}
		});
		mShell.addTool(resize);

		mShell.addShellListener(mListener);
		mShell.addListener(Events.Resize, new Listener() {
			public void handleEvent(BaseEvent be) {
				mRolledUp = false;
				roll.changeStyle("my-tool-minus");
				mOldBounds = null;
			}
		});
		mShell.getDraggable().container = Desktop.getContainer();

		mShell.open();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.mygwt.ui.client.mvc.ViewhandleEvent(net.mygwt.ui.client.mvc.AppEvent)
	 */
	protected void handleEvent(AppEvent pEvent) {
		switch (pEvent.type) {
		case DesktopEvents.ShellOpenURL:
			AppLink link = (AppLink) pEvent.data;
			String name = link.getName();
			for (int i = 1; sShellNames.get(name) != null; i++) {
				name = link.getName() + " [" + i + "]";
			}
			sShellNames.put(name, mShell);
			mShell.setText(name);
			mURL = link.getURL();
			createContent();
			Dispatcher.forwardEvent(new AppEvent(DesktopEvents.ShellCreated, mShell));
			break;
		case DesktopEvents.DockPinned:
			if (mMaximized) {
				handleDockPinned();
			}
			break;
		case DesktopEvents.DockUnPinned:
			if (mMaximized) {
				handleDockUnPinned();
			}
			break;
		}
	}

	private void createContent() {
		mFrame = new Frame(mURL);
		MyDOM.setStyleAttribute(mFrame.getElement(), "frameborder", "0");
		mFrame.setSize("100%", "100%");

		WidgetContainer c = mShell.getContent();
		c.setLayout(null);
		c.removeAll();
		c.add(mFrame);
	}

	private void handleDockPinned() {
		final Rectangle desktopBounds = Desktop.getBounds();
		final DockView dock = (DockView) Registry.get("dock");
		Rectangle r = dock.getBounds();
		if (r.x - desktopBounds.x == 0) {
			mShell.setBounds(new Rectangle(desktopBounds.x + r.width, desktopBounds.y, Desktop.getClientWidth()
					- r.width, Desktop.getClientHeight()));
		} else {
			mShell.setBounds(new Rectangle(desktopBounds.x, desktopBounds.y, Desktop.getClientWidth() - r.width,
					Desktop.getClientHeight()));
		}
	}

	private void handleDockUnPinned() {
		final Rectangle desktopBounds = Desktop.getBounds();
		mShell.setBounds(new Rectangle(desktopBounds.x, desktopBounds.y, Desktop.getClientWidth(), Desktop
				.getClientHeight()));

	}
}
